
module StringHelper (getWords, string2int, isPartOf, displayInTable) where
import Char

-- function reads input string like: word1 " word2" "word3 word4" word5 word6 " word7
-- and returns list like ["word1", "word2", "word3 word4", "word5", "word6", " word7"]
getWords :: [[Char]] -> [[Char]]
getWords [] = []
getWords ls = if rest == [[]] then [[]] else nextWord : getWords rest
                                where nextWord = fst (getNextWord ls False)
                                      rest     = snd (getNextWord ls False)

getNextWord :: [[Char]] -> Bool -> ([Char], [[Char]])
getNextWord [] _ = ([], [])
getNextWord ([]:ls) _ = ([], ls)
getNextWord (('"':[]):ls) True = (" ", ls)
getNextWord (('"':chs):ls) ifConcat =
                        if ifConcat==True then
                             if (last chs) == '"' then --string postaci {spacja}"{cokolwiek-bez-"}{spacja}"{cokolwiek-bez-spacji-i-"}"{spacja} - a wiec np "slowo "slowo" lub "slowo "slowo"" 
                               ('"':chs, ls)
                             else -- ciag byl typu: {cokolwiek} "abc "def {cokolwiek}
                               ('"':chs ++ nextWord, rest)
                        else -- w getNextWord wczesniej nie bylo "{cokolwiek}
                             if (last chs) == '"' then --string postaci {spacja}"{cokolwiek-bez-spacji-i-"}"{spacja} - a wiec np "slowo" lub "
                               (init chs, ls)
                             else
                               (chs ++ nextWord, rest)
                          where nextWord = fst (getNextWord ls True)
                                rest     = snd (getNextWord ls True)
getNextWord (chs:ls) True =
                     if (last chs) == '"' then --koniec slowa ujetego w ""
                        (' ':(init chs), ls)  
                     else -- konkatenuujemy dalej
                        (' ':chs ++ nextWord, rest)
                            where nextWord = fst (getNextWord ls True)
                                  rest     = snd (getNextWord ls True)
getNextWord (chs:ls) false = (chs, ls) -- jesli last chs ~= '"' to zwykle slowo nie ujete w "", w przeciwnym przypadku ciag nie mial  "abc  a ma  def"


{- potrzebne do updateFilm -}
string2int :: String -> Maybe Int
string2int "" = Nothing
string2int s = if (foldr (&&) True (map (isDigit) s)) 
               then Just (read s::Int) 
               else Nothing

-- porownywanie stringow, argumenty:
-- 1) string do porownania
-- 2) fragment stringa do porownania, ktorego jeszcze nie porownano
-- 3) string, w ktorym szuka sie wzoru, uciety o elementy, ktore porownano pozytywnie
-- 4) string, ktory zapamietuje ostatni string, od ktorego znaleziono podobienstwo ze wzorem
isPart :: String -> String -> String -> String -> Bool
isPart _ [] _ _ = True
isPart _ _ [] _ = False
isPart pattern (p:part) (s:ss) (l:ls)	| p == s	= isPart pattern part ss (l:ls)
					| otherwise	= isPart pattern pattern ls ls

-- funkcja ,,publiczna'', sprawdza, czy zadany wzor jest w Stringu
-- args: pattern stringToCheck
isPartOf :: String -> String -> Bool
isPartOf pattern s = isPart pattern pattern s s



-- wyswietla liste list Stringow w tablicy
displayInTable :: [[String]] -> String
displayInTable objects = 
        (' ' : displayStringsList maks (head objects)) 
        ++ "\n " ++ getTerminationLine maks ++ "\n "
        ++ (foldr (\x y -> x ++ "\n " ++ y) "" (map (displayStringsList maks) (drop 1 objects)) )
        ++ " (" ++ (show ((length objects) - 1)) ++ " rekordow)"
        where maks = getMaxForParams 0 objects

-- zwraca maksymalne wartosci szerokosci dla kazdej z kolumn tabeli (nie wieksze niz 22)
getMaxForParams :: Int -> [[String]] -> [Int]
getMaxForParams k [] = [0 | x <- [1 .. k]]
getMaxForParams k objects = 
        (if maxLen > 22 then 22 else maxLen) : 
        if k+1 > (length (head objects))-1 then
                [] 
        else
                getMaxForParams (k+1) objects
        where maxLen = maximum (map (length) (map (!! k) objects))

-- konstruluje string zawierajacy pojedynczy rzad tabeli (mogacy skladac sie z wielu linii)
displayStringsList :: [Int] -> [String] -> String
displayStringsList maks strs = 
        "|" ++ displayedLine ++ "\n " ++
        if (foldr (||) False (map (any (not . isSpace)) toDisplay)) then
                displayStringsList maks toDisplay
        else
                getTerminationLine maks
        where displayedLine = fst displayStringsListLineRet
              toDisplay = snd displayStringsListLineRet
              displayStringsListLineRet = displayStringsListLine strs maks

-- konstruluje string zawierajacy ciag znakow '-' o odpowiedniej dlugosci
getTerminationLine :: [Int] -> String
getTerminationLine maks = '|' : ['-' | x <- [1 .. ((foldr (+) 0 maks)  + 1*(length maks) - 1)]] ++ "|"

-- konstruluje pojedyncza linije rzedu tabeli
displayStringsListLine :: [String] -> [Int] -> (String, [String])
displayStringsListLine _ [] = ("", [])
displayStringsListLine [] _ = ("", [])
displayStringsListLine (s:sr) (m:mr) = 
        ((fst cellRet) ++ "|" ++ (fst nextRes), (snd cellRet) : (snd nextRes))
        where nextRes = displayStringsListLine sr mr
              cellRet = displayCell s m

-- konstruluje pojedyncza komórke linii rzedu tabeli
displayCell :: String -> Int -> (String, String)
displayCell str len = if takenLen < len then
                        (taken ++ [' ' | x <- [1 .. len-takenLen]], []) 
                      else
                        (taken, drop len str)
                      where
                        takenLen = length taken
                        taken = take len str
                      
